#include "StdAfx.h"
#include "FIT_6204_Gorodilov_Line.h"

CFIT_6204_Gorodilov_Line::CFIT_6204_Gorodilov_Line(const CFIT_6204_Gorodilov_Point p1, const CFIT_6204_Gorodilov_Point p2)
{
	if (comparePoints(&p1, &p2) < 0) {		
		m_pLeft = p1;
		m_pRight = p2;
	} else {
		m_pLeft = p2;
		m_pRight = p1;
	}
	m_pLeft.status = RECT_POINT_LEFT;
	m_pRight.status = RECT_POINT_RIGHT;
}

CFIT_6204_Gorodilov_Line::CFIT_6204_Gorodilov_Line()
: m_pLeft(0)
, m_pRight(0)
{
	m_pLeft.status = RECT_POINT_LEFT;
	m_pRight.status = RECT_POINT_RIGHT;
}

CFIT_6204_Gorodilov_Line::~CFIT_6204_Gorodilov_Line(void)
{
}

const CFIT_6204_Gorodilov_Point CFIT_6204_Gorodilov_Line::GetLeftPoint(void) const
{
	CFIT_6204_Gorodilov_Point result = m_pLeft;
	result.status = RECT_POINT_LEFT;
	result.parent = (CFIT_6204_Gorodilov_Line*)this;
	return result;
}

const CFIT_6204_Gorodilov_Point CFIT_6204_Gorodilov_Line::GetRightPoint(void) const
{
	CFIT_6204_Gorodilov_Point result = m_pRight;
	result.status = RECT_POINT_RIGHT;
	result.parent = (CFIT_6204_Gorodilov_Line*)this;
	return result;
}

int comparePoints(const void *arg1, const void *arg2)  {
	CFIT_6204_Gorodilov_Point *p1 = (CFIT_6204_Gorodilov_Point *)arg1;
	CFIT_6204_Gorodilov_Point *p2 = (CFIT_6204_Gorodilov_Point *)arg2;
	if (p1->x < p2->x) {
		return -1;
	} else {
		if (p1->x == p2->x) {
			if (p1->y < p2->y) {
				return -1;
			} else {
				if (p1->y == p2->y) {
					return (p1->status < p2->status);
				}
				return 1;
			}
		} else {
			return 1;
		}
	}
}

int CFIT_6204_Gorodilov_Line::UpdatePoints(const CPoint p1, const CPoint p2)
{
	if (comparePoints(&p1, &p2) < 0) {		
		m_pLeft = p1;
		m_pRight = p2;
		m_pLeft.status = RECT_POINT_LEFT;
		m_pRight.status = RECT_POINT_RIGHT;
		return -1;
	} else {
		m_pLeft = p2;
		m_pRight = p1;
		m_pLeft.status = RECT_POINT_LEFT;
		m_pRight.status = RECT_POINT_RIGHT;
		return 1;
	}
}

CFIT_6204_Gorodilov_Point& CFIT_6204_Gorodilov_Point::operator =(const CPoint& b) {
	this->y = b.y;
	this->x = b.x;
	return *this;
}

double CFIT_6204_Gorodilov_Line::GetCrossPoint(const double x) {
	if (x < m_pLeft.x) {
		return -1;
	}
	if (x > m_pRight.x) {
		return -1;
	}
	double xt = m_pRight.x - m_pLeft.x;
	double yt = m_pRight.y - m_pLeft.y;
	double y = (double)(yt*(x - m_pRight.x)) / xt + m_pRight.y;
	return y;
}

BOOL crossLines(CFIT_6204_Gorodilov_Line *l1, CFIT_6204_Gorodilov_Line *l2, CFIT_6204_Gorodilov_Point &p) {
	if (!l1)
		return FALSE;
	if (!l2)
		return FALSE;
	/*if (l1->GetRightPoint().y >= l2->GetRightPoint().y) {
		return FALSE;
	}*/

	double x1 = p.x;
	double y1 = l1->GetCrossPoint(x1);
	double y2 = l2->GetCrossPoint(x1);
	double x2 = 0;
	double y3 = 0.0;
	double y4 = 0.0;
	if (l1->GetRightPoint().x < l2->GetRightPoint().x) {
		x2 = l1->GetRightPoint().x;
		y4 = l1->GetRightPoint().y;
		y3 = l2->GetCrossPoint(x2);
	} else {
		x2 = l2->GetRightPoint().x;
		y3 = l2->GetRightPoint().y;
		y4 = l1->GetCrossPoint(x2);
	}
	if (y3 < y4) {
		return FALSE;
	}
	if ((y3 - y4) < 1e-20) {
		if (l1->GetRightPoint().x == l2->GetRightPoint().x) {
			return FALSE;
		}
		p.x = x2;
		p.y = y3;
		p.status = INTERSECTION;
		p.parent = l1;
		p.parent2 = l2;
		return TRUE;
	}
	double b = (double)(x2 - x1)/((y1 - y2)/(y3 - y4) + 1.0);
	p.x = x2 - b;
	p.y = l1->GetCrossPoint(p.x);
	p.status = INTERSECTION;
	p.parent = l1;
	p.parent2 = l2;
	return TRUE;
}